﻿using System;
using System.Collections;
using System.Collections.Specialized;
using System.Collections.Generic;
using System.Text;
using System.ServiceProcess;

namespace Wagner.SharePoint.Utilities
{
	/// <summary>
	/// Windows Services Utilities
	/// </summary>
	/// <remarks>Some methods are from: http://www.csharp-examples.net/restart-windows-service/</remarks>
	internal static class ServiceUtilities
	{
		public const string SharePointTimerServiceName = "SPTimerV3";

		public static void RestartSharePointTimerService()
		{
			RestartService(SharePointTimerServiceName, 30000);
		}
		
		public static void GetServices()
		{
			ServiceController[] services = ServiceController.GetServices();
		}

		public static void StartService(string serviceName, int timeoutMilliseconds)
		{
			if (!ServiceVerified(SharePointTimerServiceName))
				return;

			ServiceController service = new ServiceController(serviceName);
			try
			{
				TimeSpan timeout = TimeSpan.FromMilliseconds(timeoutMilliseconds);

				service.Start();
				service.WaitForStatus(ServiceControllerStatus.Running, timeout);
			}
			catch(Exception ex)
			{
				Logger.Log(ex);
				throw;
			}
		}

		public static void StopService(string serviceName, int timeoutMilliseconds)
		{
			if (!ServiceVerified(SharePointTimerServiceName))
				return;

			ServiceController service = new ServiceController(serviceName);
			try
			{
				TimeSpan timeout = TimeSpan.FromMilliseconds(timeoutMilliseconds);

				service.Stop();
				service.WaitForStatus(ServiceControllerStatus.Stopped, timeout);
			}
			catch(Exception ex)
			{
				Logger.Log(ex);
				throw;
			}
		}

		public static void RestartService(string serviceName, int timeoutMilliseconds)
		{
			if (!ServiceVerified(SharePointTimerServiceName))
				return;

			ServiceController service = new ServiceController(serviceName);
			try
			{
				int millisec1 = Environment.TickCount;
				TimeSpan timeout = TimeSpan.FromMilliseconds(timeoutMilliseconds);

				service.Stop();
				service.WaitForStatus(ServiceControllerStatus.Stopped, timeout);

				// count the rest of the timeout
				int millisec2 = Environment.TickCount;
				timeout = TimeSpan.FromMilliseconds(timeoutMilliseconds - (millisec2 - millisec1));

				service.Start();
				service.WaitForStatus(ServiceControllerStatus.Running, timeout);
			}
			catch(Exception ex)
			{
				Logger.Log(ex);
				throw;
			}
		}

		/// <summary>
		/// Returns true if the service exists.
		/// </summary>
		/// <param name="serviceName"></param>
		/// <returns></returns>
		public static bool ServiceExists(string serviceName)
		{
			// get list of Windows services
			ServiceController[] services = ServiceController.GetServices();

			// try to find service name
			foreach (ServiceController service in services)
			{
				if (service.ServiceName == serviceName)
					return true;
			}
			return false;
		}
		
		/// <summary>
		/// Returns true if the service exists. If not, a "Service not found" message is written to the console.
		/// </summary>
		/// <param name="serviceName"></param>
		/// <returns></returns>
		private static bool ServiceVerified(string serviceName)
		{
			if (ServiceExists(SharePointTimerServiceName))
				return true;
			else
			{
				Console.WriteLine(string.Format("Service '{0}' does not exist.", SharePointTimerServiceName));
				return false;
			}
		}

	}
}
